<!doctype html>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script src="../assert_selection.js"></script>
<script src="spellcheck_test.js"></script>

<script>
test(() => assert_not_equals(window.internals, undefined),
     'This test requires internals to set editing behavior.');

test(() => assert_not_equals(window.eventSender, undefined),
     'This test requires event sender to simulate keyboard and mouse actions.');

// There seems to be some bug with testharness.js that the whole testharness is
// considered as ran to complete even before there are still tests to be
// created. As a workaround, we manually hold an dummy async_test that finishes
// after all test cases finish.
const testHolder = async_test(() => assert_true(true), 'Dummy test holder');
testHolder.finishedCount = 0;

function contextClickOnSelection(selection) {
  const range = selection.getRangeAt(0);
  const document = range.startContainer.ownerDocument;
  const rect = range.getClientRects()[0];
  const x = document.offsetLeft + rect.left + rect.width / 2;
  const y = document.offsetTop + rect.top + rect.height / 2;
  eventSender.mouseMoveTo(x, y);
  const contextMenuElements = eventSender.contextClick();
  // Esc key to hide the context menu.
  eventSender.keyDown('Escape', null);
  return contextMenuElements;
}

function assertContextMenuSuggestion(sample, expected) {
  var title = `Context clicking on selected "${sample.selection.toString()}" ` +
                (expected ? `gives suggestion "${expected}".` : 'does not give any suggestion.');
  test(() => {
    const suggestions = contextClickOnSelection(sample.selection);
    assert_equals(suggestions[suggestions.length - 1], expected || '<separator>');
  }, title);
  sample.remove();

  if (++testHolder.finishedCount == 9)
    testHolder.done();
}

function doubleClickAt(node, offset) {
  const document = node.ownerDocument;
  const range = document.createRange();
  range.setStart(node, offset);
  const rect = range.getClientRects()[0];
  const x = document.offsetLeft + rect.left;
  const y = document.offsetTop + rect.top + rect.height / 2;
  eventSender.mouseMoveTo(x, y);
  eventSender.mouseDown();
  eventSender.mouseUp();
  eventSender.mouseDown();
  eventSender.mouseUp();
}

spellcheck_test(
    '<div contenteditable>^wellcome| home.</div>',
    '',
    '<div contenteditable>#wellcome# home.</div>',
    {
      title: 'Has marker on initial misspelling in "wellcome home.".',
      callback: sample => assertContextMenuSuggestion(sample, 'welcome')
    });

spellcheck_test(
    '<div contenteditable>It should be ^upper case|.</div>',
    '',
    '<div contenteditable>It should be #upper case#.</div>',
    {
      title: 'Has marker on initial multi-word misspelling in "It should be upper case.".',
      callback: sample => assertContextMenuSuggestion(sample, 'uppercase')
    });

spellcheck_test(
    '<div contenteditable>hello,^ wellcome |home.</div>',
    '',
    '<div contenteditable>hello, #wellcome# home.</div>',
    {
      title: 'Has marker on initial misspelling in "hello, wellcome home.".',
      callback: sample => assertContextMenuSuggestion(sample, 'welcome')
    });

spellcheck_test(
    '<div contenteditable>Hi, ^_wellcome_| home.</div>',
    '',
    '<div contenteditable>Hi, _#wellcome#_ home.</div>',
    {
      title: 'Has marker on initial misspelling in "Hi, wellcome home.".',
      callback: sample => assertContextMenuSuggestion(sample, 'welcome')
    });

spellcheck_test(
    '<div contenteditable>^wellcome!|</div>',
    '',
    '<div contenteditable>#wellcome#!</div>',
    {
      title: 'Has marker on initial misspelling in "wellcome!".',
      callback: sample => assertContextMenuSuggestion(sample, 'welcome')
    });

spellcheck_test(
    '<div contenteditable>we^llco|me home.</div>',
    '',
    '<div contenteditable>#wellcome# home.</div>',
    {
      title: 'Has marker on initial misspelling in "wellcome home." with "llco" selected.',
      callback: sample => assertContextMenuSuggestion(sample)
    });

spellcheck_test(
    '<div contenteditable>^wellcome home|.</div>',
    '',
    '<div contenteditable>#wellcome# home.</div>',
    {
      title: 'Has marker on initial misspelling in "wellcome home." with "wellcome home" selected.',
      callback: sample => assertContextMenuSuggestion(sample)
    });

// Note: for the following test cases related to double clicking, the selection
// dependends on platform (Win selects a trailing space while other platforms do
// not), which, however, do not affect the context menu spelling suggestions.

spellcheck_test(
    '<div contenteditable>wellcome home.</div>',
    document => {
      var div = document.querySelector('div');
      doubleClickAt(div.firstChild, 4);
    },
    '<div contenteditable>#wellcome# home.</div>',
    {
      title: 'Has marker on misspelled word "wellcome" after selecting it with double-clicking',
      callback: sample => assertContextMenuSuggestion(sample, 'welcome')
    });

spellcheck_test(
    '<div contenteditable>wellcome_ home.</div>',
    document => {
      var div = document.querySelector('div');
      doubleClickAt(div.firstChild, 4);
    },
    '<div contenteditable>#wellcome#_ home.</div>',
    {
      title: 'Has marker on misspelled word "wellcome" after selecting it and its trailing underscore with double-clicking',
      callback: sample => assertContextMenuSuggestion(sample, 'welcome')
    });
</script>
